package com.xplay.xpocker.core.lock;

import org.springframework.stereotype.Service;
import sun.security.jca.GetInstance;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;

@Service
public class LocalLockServer implements LockServer {
    private static LocalLockServer localLockServer;

    public static LocalLockServer getInstance() {
        return localLockServer;
    }

    private final Map<String, ReentrantLock> LOCK_MAP = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() {
        localLockServer = this;
    }

    private ReentrantLock getLock(String key) {
        return LOCK_MAP.computeIfAbsent(key, (k) -> new ReentrantLock());
    }

    @Override
    public <T> T lock(String key, Supplier<T> supplier) {
        return lock(key, 0, null, supplier);
    }

    @Override
    public <T> T lock(String key, long time, TimeUnit timeUnit, Supplier<T> supplier) {
        ReentrantLock lock = getLock(key);
        boolean getLock = true;
        try {
            if (timeUnit != null) {
                getLock = lock.tryLock(time, timeUnit);
            } else {
                lock.lock();
            }
            if (!getLock) {
                return null;
            }
            T result = supplier.get();
            lock.unlock();
            return result;
        } catch (Exception e) {
            lock.unlock();
            return null;
        }
    }
}
